<?php
namespace addons\wddj\command;

use app\api\model\wddj\Config;
use GatewayWorker\BusinessWorker;
use GatewayWorker\Gateway;
use GatewayWorker\Register;
use think\console\Command;
use think\console\Input;
use think\console\Output;
use think\Db;
use Workerman\Worker;

class Wddj extends Command
{
    protected function configure()
    {
        $this->setName('wddj')
            ->setDescription('启动 GatewayWorker 服务')
            ->addArgument('action', null, 'Action to perform (start)')
            ->addOption('daemon', 'd', null, '是否以守护进程模式启动');
    }


    protected function execute(Input $input, Output $output)
    {
        $action = $input->getArgument('action');
        $daemon = $input->getOption('daemon');  // 获取 -d 参数

        if ($action === 'start') {
            $this->startServer($output, $daemon);
        } elseif ($action === 'stop') {
            $this->stop($output);
        } elseif ($action === 'restart') {
            $this->restart($output, $daemon);
        } else {
            $output->writeln("无效的命令，请使用 'start' 启动服务。");
        }
    }


    protected function startServer(Output $output, $daemon)
    {
        \think\Config::set('database.break_reconnect', true);
        Db::connect();
        $configObj = (new Config())->get(1);
        $websocket_port = $configObj['websocket_port'];
        $internal_start_port = $configObj['internal_start_port'];
        $gateway_process_number = $configObj['gateway_process_number'];
        $worker_process_number = $configObj['worker_process_number'];

        //定义端口
        $port = $configObj['register_port'];  //服务注册地址,无需对外开放,未被占用的端口即可，默认1238
        new Register('text://0.0.0.0:' . $port);

        //初始化 bussinessWorker 进程
        $worker = new BusinessWorker();
        $worker->name = 'chatWorker';  //进程名
        $worker->count = $worker_process_number;  //进程数,设为CPU核数的1-3倍,默认4
        $worker->registerAddress = '127.0.0.1:' . $port;

        // 设置处理业务的类,此处制定Events的命名空间
        $worker->eventHandler = '\addons\wddj\library\Events';

        // 初始化 gateway 进程
        $context = array(
            'ssl' => array(
                'local_cert' => ROOT_PATH . 'public' . $configObj['wss_cert'],  // 也可以是crt文件
                'local_pk' => ROOT_PATH . 'public' . $configObj['wss_key'],
                'verify_peer' => false,
            )
        );
        $gateway = new Gateway("websocket://0.0.0.0:$websocket_port", $context);
        $gateway->transport = 'ssl';
        $gateway->name = 'chatGateway'; //Gateway进程名
        $gateway->count = $gateway_process_number;  //Gateway进程数,设置为CPU核数相等的数量最好,默认4
        $gateway->lanIp = '127.0.0.1';
        $gateway->startPort = $internal_start_port;  //开始端口  内部通讯端口,无需对外开放,未被占用的端口即可，默认2000
        $gateway->pingInterval = 60;
        $gateway->pingNotResponseLimit = 5;
        $gateway->pingData = 'pong';
        $gateway->registerAddress = '127.0.0.1:' . $port;

        // 设置守护进程模式
        if ($daemon) {
            Worker::$daemonize = true;  // 如果传入 -d 参数，则设置为守护进程
        } else {
            Worker::$daemonize = false;  // 默认不设置守护进程
        }

        if (!is_dir(ROOT_PATH . '/runtime/wddj/')) {
            wddj_mkdirs(ROOT_PATH . '/runtime/wddj/',0755);
        }

        // 检查日志文件是否存在
        $gateway_worker_file = ROOT_PATH . '/runtime/wddj/gateway_worker.log';
        if (!file_exists($gateway_worker_file)) {
            touch($gateway_worker_file);  // 创建文件
        }

        // 检查 PID 文件是否存在
        $my_crontab_file = ROOT_PATH . '/runtime/wddj/MyCrontab.pid';
        if (!file_exists($my_crontab_file)) {
            touch($my_crontab_file);  // 创建文件
        }

        Worker::$logFile = ROOT_PATH . '/runtime/wddj/gateway_worker.log';  // 日志文件
        Worker::$pidFile = ROOT_PATH . '/runtime/wddj/MyCrontab.pid';  // PID 文件

        // 运行所有 Worker;
        Worker::runAll();

        // 输出提示信息
        $output->writeln("GatewayWorker 服务已启动");
    }



    protected function stop(Output $output)
    {
        // 检查是否存在 PID 文件，PID 文件用于记录进程 ID
        $pidFile = ROOT_PATH.'/runtime/wddj/MyCrontab.pid';

        if (file_exists($pidFile)) {
            // 读取 PID 文件
            $pid = file_get_contents($pidFile);

            // 如果 PID 文件存在且有效，发送 SIGTERM 信号结束进程
            if ($pid) {
                // 向进程发送终止信号
                if (posix_kill($pid, SIGTERM)) {
                    $output->writeln("GatewayWorker 服务已停止");
                } else {
                    $output->writeln("停止 GatewayWorker 服务失败，无法发送终止信号");
                }
            } else {
                $output->writeln("无效的 PID 文件，无法停止服务");
            }
        } else {
            $output->writeln("PID 文件不存在，服务可能未启动");
        }
    }


    protected function restart(Output $output, $daemon)
    {

        // 获取 PID 文件路径
        $pidFile = ROOT_PATH . '/runtime/wddj/MyCrontab.pid';

        if (file_exists($pidFile)) {
            // 读取 PID
            $pid = file_get_contents($pidFile);

            if ($pid) {
                // 向进程发送 SIGTERM 信号停止服务
                if (posix_kill($pid, SIGTERM)) {
                    $output->writeln("正在停止 GatewayWorker 服务...");
                    // 等待一定时间确保进程完全停止
                    sleep(2);

                    // 重新启动所有 Worker 进程
                    $this->startServer($output,$daemon);
                    $output->writeln("GatewayWorker 服务已重启");
                } else {
                    $output->writeln("停止 GatewayWorker 服务失败，无法发送终止信号");
                }
            } else {
                $output->writeln("无效的 PID 文件，无法停止服务");
            }
        } else {
            $output->writeln("PID 文件不存在，服务可能未启动");
        }
    }


}